package net.neptech.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.util.WxMaConfigHolder;
import cn.dev33.satoken.stp.StpUtil;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import net.neptech.domian.model.LoginUser;
import net.neptech.exception.BusinessException;
import net.neptech.feign.RemoteUserService;
import net.neptech.repository.AuthMapper;
import net.neptech.model.sys.User;
import net.neptech.service.AuthService;
import net.neptech.utils.SecurityUtils;
import net.neptech.utils.StringUtils;
import net.neptech.vm.ResponseResult;
import net.neptech.vm.constant.SecurityConstants;
import net.neptech.vm.constant.UserConstants;
import net.neptech.vm.enums.ResultStatusEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.UUID;

/**
 * @Author: liyuxiang
 * @Date: 2025/8/5 16:55
 */
@Service
@Slf4j
public class AuthServiceImpl implements AuthService {
    @Autowired
    private AuthMapper authMapper;
    @Autowired
    private RemoteUserService remoteUserService;
    @Autowired
    private WxMaService wxMaService;

    @Override
    public String login(String username, String password) {
        // 1. 根据手机号查询用户
        User user = authMapper.findUserByUsername(username);
        // 2. 如果不存在抛出异常，提示用户名或密码错误
        if (user == null) {
            throw new BusinessException(ResultStatusEnum.USERNAME_OR_PASSWORD_ERROR);
        }
        if (!SecurityUtils.matchesPassword(password, user.getPassword())) {
            throw new BusinessException(ResultStatusEnum.USERNAME_OR_PASSWORD_ERROR);
        }
        // 3. 使用Sa-Token生成token
        StpUtil.login(user.getUserId());

        // 4. 构建登录用户基础信息
        LoginUser loginUser = buildLoginUser(user);

        // 5. 通过Feign调用获取用户权限和角色
//        try {
//            System.out.println("permissionFeignClient.getUserPermissions()"+permissionFeignClient.getUserPermissions());
//            Set<String> permissions = permissionFeignClient.getUserPermissions().getData();
//            Set<String> roles = permissionFeignClient.getUserRoles().getData();
//
//            loginUser.setPermissions(permissions != null ? permissions : new HashSet<>());
//            loginUser.setRoles(roles != null ? roles : new HashSet<>());
//
//            System.out.println("获取到的权限: " + permissions);
//            System.out.println("获取到的角色: " + roles);
//        } catch (Exception e) {
//            System.err.println("获取用户权限失败: " + e.getMessage());
//            // 如果获取权限失败，设置为空集合
//            loginUser.setPermissions(new HashSet<>());
//            loginUser.setRoles(new HashSet<>());
//        }

        // 6. 将完整的用户信息存储到Session中
        StpUtil.getTokenSession().set(SecurityConstants.LOGIN_USER, loginUser);

        // 7. 返回Sa-Token生成的token
        return StpUtil.getTokenValue();
    }

    /**
     * 构建登录用户基础信息
     */
    private LoginUser buildLoginUser(User user) {
        LoginUser loginUser = new LoginUser();
        loginUser.setUsername(user.getUsername());
        loginUser.setUserId(user.getUserId());
//        loginUser.setToken(StpUtil.getTokenValue());
        // 权限和角色将在外部通过Feign调用设置
        return loginUser;
    }

    @Override
    public void register(String username, String password, String telphone) {
        // 用户名或密码为空 错误
        if (StringUtils.isAnyBlank(username, password)) {
            throw new BusinessException(ResultStatusEnum.BAD_REQUEST.getCode(), "用户/密码必须填写");
        }
        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
            throw new BusinessException(ResultStatusEnum.BAD_REQUEST.getCode(), "账户长度必须在2到20个字符之间");
        }
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            throw new BusinessException(ResultStatusEnum.BAD_REQUEST.getCode(), "密码长度必须在5到20个字符之间");
        }
        User registerUser = new User();
        registerUser.setUsername(username);
        registerUser.setUserContact(telphone);
        registerUser.setPassword(password);
        remoteUserService.registerUserInfo(registerUser);
    }

    @Override
    public void logout() {
        StpUtil.logout();
    }

    @Override
    public String wxLogin(String code) {
        if (StringUtils.isBlank(code)) {
            return "empty jscode";
        }
        try {
            //根据code获取openid
            WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code);
            if (session == null || StringUtils.isBlank(session.getOpenid())) {
                throw new BusinessException(ResultStatusEnum.BAD_REQUEST.getCode(), "获取openid失败");
            }
            log.info("session: {}", session.getOpenid());
            //判断用户是否存在
            User user = new User();
            user.setOpenId(session.getOpenid());
            ResponseResult<User> selectedUser = remoteUserService.selectUser(user);
            if (selectedUser == null || selectedUser.getData() == null) {
                //用户不存在，注册新用户
                user.setUsername("微信用户" + UUID.randomUUID().toString().replaceAll("-", ""));
                user.setPassword("123456");
                user = remoteUserService.registerUserInfo(user).getData();
                log.info("user: {}", user);
            } else {
                user = selectedUser.getData();
            }
            //使用Sa-Token生成token
            StpUtil.login(user.getUserId());
            //构建登录用户基础信息
            LoginUser loginUser = buildLoginUser(user);
            //将完整的用户信息存储到Session中
            StpUtil.getTokenSession().set(SecurityConstants.LOGIN_USER, loginUser);
            //返回Sa-Token生成的token
            return StpUtil.getTokenValue();
        } catch (WxErrorException e) {
            log.error(e.getMessage(), e);
//            throw new WxLoginException(e.getMessage());
        } finally {
            WxMaConfigHolder.remove();//清理ThreadLocal
        }
        return "";
    }
}
